package com.wsoft.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wsoft.constant.redis.RedisKeyConstant;
import com.wsoft.core.annotation.GetRedisCache;
import com.wsoft.core.annotation.InitRedisCache;
import com.wsoft.core.cmd.DataPermSourceService;
import com.wsoft.core.exception.Asserts;
import com.wsoft.entity.BaseEntity;
import com.wsoft.system.dto.SysOrganizationDTO;
import com.wsoft.system.entity.SysMemberOrgPostRelationEntity;
import com.wsoft.system.entity.SysOrganizationEntity;
import com.wsoft.system.manager.SysOrganizationManager;
import com.wsoft.system.mapper.SysOrganizationMapper;
import com.wsoft.system.query.org.OrgInsertQuery;
import com.wsoft.system.query.org.OrgListQuery;
import com.wsoft.system.query.org.OrgSelectQuery;
import com.wsoft.system.query.org.OrgUpdateQuery;
import com.wsoft.system.service.ISysMemberOrgPostRelationService;
import com.wsoft.system.service.ISysOrganizationService;
import com.wsoft.vo.SysOrganizationVO;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zhonglj
 * @since 2024年09月06日 14:10:29
 */
@Service(value = "sysOrganizationService")
public class SysOrganizationServiceImpl extends ServiceImpl<SysOrganizationMapper, SysOrganizationEntity> implements ISysOrganizationService , DataPermSourceService {
    private static final Long ORG_TOP_PARENT_LEVEL = 0L;
    @Resource
    private ISysMemberOrgPostRelationService memberOrgPostRelationService;

    @Resource
    private SysOrganizationManager sysOrganizationManager;
    @Override
    public List<SysOrganizationEntity> listAllOrgWithCache() {
       return sysOrganizationManager.listAllOrgWithCache();
    }

    @Override
    public List<SysOrganizationEntity> selectOrgBy(Long memberId) {
        List<SysMemberOrgPostRelationEntity> relations = memberOrgPostRelationService.getPostListByMember(memberId);

        if (CollUtil.isEmpty(relations)) {
            return null;
        }
        List<Long> orgIds = relations.stream().map(SysMemberOrgPostRelationEntity::getOrgId).collect(Collectors.toList());
        return listByIds(orgIds);
    }

    @Override
    @InitRedisCache(type =  RedisKeyConstant.CACHE_TYPE_ALL_DEPT,
                    value = RedisKeyConstant.REDIS_NULL)
    public boolean insert(OrgInsertQuery query) {
        SysOrganizationDTO dto = Convert.convert(SysOrganizationDTO.class, query);
        setOrgCode(dto);
        // 检查代码是否重复
        QueryWrapper<SysOrganizationEntity> codeQuery = new QueryWrapper<>();
            codeQuery.lambda().eq(SysOrganizationEntity::getCode,dto.getCode());
        if (count(codeQuery) > 0) {
            Asserts.fail("[sys.code.exist]");
        }
        // 校验父级组织是否存在
        if (dto.getPaId() != null) {
            SysOrganizationEntity parent = getById(dto.getPaId());
            if (parent == null) {
                Asserts.fail("[sys.org.pa.not.exist]");
            }
        } else {
            // 设置上级部门为0
            dto.setPaId(ORG_TOP_PARENT_LEVEL);
        }
        SysOrganizationEntity entity = Convert.convert(SysOrganizationEntity.class, dto);
        boolean b = save(entity);
        if (b){
            SysOrganizationEntity update = new SysOrganizationEntity();
            update.setId(entity.getId());
            update.setOrgId(entity.getId());
            return updateById(update);
        }
        else {
            return false;
        }
    }

    @Override
    @InitRedisCache(types = {RedisKeyConstant.ORG_CACHE, RedisKeyConstant.CACHE_TYPE_ALL_DEPT },
                    values = {"id",  RedisKeyConstant.REDIS_NULL})
    public boolean update(OrgUpdateQuery query) {
        SysOrganizationDTO dto =  Convert.convert(SysOrganizationDTO.class, query);
        // 检查代码是否重复
        QueryWrapper<SysOrganizationEntity> codeQuery = new QueryWrapper<>();
        if (dto.getId() != null) {
            codeQuery.lambda().ne(BaseEntity::getId,dto.getId())
                    .eq(SysOrganizationEntity::getCode,dto.getCode());
        }
        else {
            codeQuery.lambda().eq(SysOrganizationEntity::getCode,dto.getCode());
        }
        if (count(codeQuery) > 0) {
            Asserts.fail("[sys.code.exist]");
        }
        // 校验父级组织是否存在
        if (dto.getPaId() != null && dto.getPaId() != 0) {
            SysOrganizationEntity parent = getById(dto.getPaId());
            if (parent == null) {
                Asserts.fail("[sys.org.pa.not.exist]");
            }
        } else {
            // 设置上级部门为0
            dto.setPaId(ORG_TOP_PARENT_LEVEL);
        }
        SysOrganizationEntity entity = Convert.convert(SysOrganizationEntity.class, dto);
        return updateById(entity);
    }

    @Override
    @GetRedisCache(type = RedisKeyConstant.ORG_CACHE,
                   value = RedisKeyConstant.REDIS_SELF )
    public SysOrganizationEntity getOrgById(Long id) {
        return getById(id);
    }

    @Override
    @InitRedisCache(types = {RedisKeyConstant.ORG_CACHE, RedisKeyConstant.CACHE_TYPE_ALL_DEPT },
            values = {RedisKeyConstant.REDIS_SELF, RedisKeyConstant.REDIS_NULL})
    public boolean delete(Long id) {
        QueryWrapper<SysOrganizationEntity> query = new QueryWrapper<>();
        query.lambda().eq(SysOrganizationEntity::getPaId,id);
        if (count(query)>0){
            Asserts.fail("[sys.org.del.sub]");
        }
        return removeById(id);
    }

    @Override
    public List<SysOrganizationEntity> getOrgList(OrgListQuery listQuery) {
        QueryWrapper<SysOrganizationEntity> query = new QueryWrapper<>();
        //父id
        if (listQuery.getPaId()!=null){
            query.lambda().eq(SysOrganizationEntity::getPaId,listQuery.getPaId());
        }
        //编码
        if (StrUtil.isNotBlank(listQuery.getCode())){
            query.lambda().eq(SysOrganizationEntity::getCode,listQuery.getCode());
        }
        //全称
        if (StrUtil.isNotBlank(listQuery.getName())){
            query.lambda().eq(SysOrganizationEntity::getName,listQuery.getName());
        }
        //类型
        if (StrUtil.isNotBlank(listQuery.getType())){
            query.lambda().eq(SysOrganizationEntity::getName,listQuery.getType());
        }
        query.lambda().orderByAsc(SysOrganizationEntity::getSort);
        return list(query);
    }

    @Override
    public List<SysOrganizationVO> selectOrgListTree() {
        List<SysOrganizationEntity> list = list();
        List<SysOrganizationVO> collect = list.stream().map(e -> Convert.convert(SysOrganizationVO.class, e)).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(list)) {
            return buildSysOrganizationVO(collect);
        }
        return CollUtil.newArrayList();
    }

    @Override
    public List<SysOrganizationVO> selectOrgListTreeByQuery(OrgSelectQuery query) {
        List<SysOrganizationEntity> list = listAllOrgWithCache();
        //筛选父组织id数组
        List<SysOrganizationEntity> filterByParent = filterByParent(list, query.getIds());
        //筛选组织类型
        List<SysOrganizationEntity> filterByType = filterByType(filterByParent, query.getType());
        //筛选显示层级
        List<SysOrganizationVO> collect = filterByType.stream().map(e -> Convert.convert(SysOrganizationVO.class, e)).collect(Collectors.toList());
        List<SysOrganizationVO> treeOrg = buildSysOrganizationVO(collect);
        if(query.getLevel()==null){
            return treeOrg;
        }
        //筛选完数据取出第一层
        List<SysOrganizationEntity> firstLevel = treeOrg.stream().map(e -> Convert.convert(SysOrganizationEntity.class, e)).collect(Collectors.toList());
        List<SysOrganizationEntity> filterByLevel = filterByLevel(filterByType, firstLevel, null, query.getLevel());
        List<SysOrganizationVO> result = filterByLevel.stream().map(e -> Convert.convert(SysOrganizationVO.class, e)).collect(Collectors.toList());
        return buildSysOrganizationVO(result);
    }
    /**
    * 根据显示层级筛选
    */
    private static List<SysOrganizationEntity> filterByLevel(List<SysOrganizationEntity> allOrganizations,
                                                    List<SysOrganizationEntity> currentLevelOrganizations,
                                                    List<Long> parentIds,
                                                    int maxLevel) {
        List<SysOrganizationEntity> result = new ArrayList<>(currentLevelOrganizations);
        if (maxLevel > 0) {
            List<Long> nextLevelParentIds = currentLevelOrganizations.stream()
                    .map(SysOrganizationEntity::getId)
                    .collect(Collectors.toList());
            List<SysOrganizationEntity> nextLevelOrganizations = allOrganizations.stream()
                    .filter(org -> nextLevelParentIds.contains(org.getPaId()))
                    .collect(Collectors.toList());
            result.addAll(filterByLevel(allOrganizations, nextLevelOrganizations, nextLevelParentIds, maxLevel - 1));
        }
        return result;
    }
    /**
     * 根据父组织ID筛选
     */
    private List<SysOrganizationEntity> filterByParent(List<SysOrganizationEntity> organizations, List<Long> parentIds) {
        // 父组织ID为空，返回所有组织
        if (parentIds == null || parentIds.isEmpty()) {
            return organizations;
        }
        List<SysOrganizationEntity> list = new ArrayList<>();
        parentIds.forEach(parentId -> {
            SysOrganizationEntity org = this.getOrgById(parentId);
            List<SysOrganizationEntity> collect = organizations.stream().filter(e -> e.getAuthCode().startsWith(org.getAuthCode())).collect(Collectors.toList());
            list.addAll(collect);
        });
        return list.stream()
                // 去重复
                .collect(Collectors.toMap(SysOrganizationEntity::getId, p -> p, (p1, p2) -> p1))
                .values()
                .stream()
                // sort升序
                .sorted(Comparator.comparingInt(SysOrganizationEntity::getSort))
                .collect(Collectors.toList());
    }

    /**
     * 根据组织类型筛选
     */
    private static List<SysOrganizationEntity> filterByType(List<SysOrganizationEntity> organizations, String orgType) {
        if (StrUtil.isBlank(orgType)){
            return organizations;
        }
        return organizations.stream()
                .filter(org -> orgType.equals(org.getType()))
                .collect(Collectors.toList());
    }


    private void setOrgCode(SysOrganizationDTO dto) {
        String code = "";
        // 获取父级代码
        SysOrganizationEntity parent = getById(dto.getPaId());
        QueryWrapper<SysOrganizationEntity> query = new QueryWrapper<>();
        //找出该节点下最大编码
        if (parent != null && StrUtil.isNotBlank(parent.getCode())) {
            query.lambda().eq(SysOrganizationEntity::getPaId,dto.getPaId());
        }
        else {
            query.lambda().eq(SysOrganizationEntity::getPaId,ORG_TOP_PARENT_LEVEL);
        }
            List<SysOrganizationEntity> list = list(query);
            List<String> collect = list.stream().map(SysOrganizationEntity::getAuthCode).collect(Collectors.toList());
            List<String > result= new ArrayList<>();
            collect.forEach(e->{
                result.add(e.substring(e.length()-3));
            });

            int maxOrderNumber = result.stream()
                    .mapToInt(Integer::parseInt)
                    .max()
                    .orElse(0);

            // 拼接当前组织编码
            int nextOrderNumber = maxOrderNumber + 1;
            if (maxOrderNumber==0){
                code="001";
            }
            // 将整数转换回指定格式的字符串（如果需要保持前导零
            else {
            code = String.format("%03d", nextOrderNumber);
        }
            if (parent==null){
                dto.setAuthCode(code);
            }else{
                dto.setAuthCode(parent.getAuthCode()+code);
            }
        }

    private List<SysOrganizationVO> buildSysOrganizationVO(List<SysOrganizationVO> vos) {
        List<SysOrganizationVO> returnList = new ArrayList<>();
        List<Long> tempList = new ArrayList<>();
        for (SysOrganizationVO vo : vos) {
            tempList.add(vo.getId());
        }
        for (SysOrganizationVO vo : vos) {
            if (!tempList.contains(vo.getPaId())) {
                recursionFn(vos, vo);
                returnList.add(vo);
            }
        }
        if (returnList.isEmpty()) {
            returnList = vos;
        }
        return returnList;
    }

    private void recursionFn(List<SysOrganizationVO> vos, SysOrganizationVO vo) {
        List<SysOrganizationVO> childList = getChildList(vos, vo);
        vo.setChildren(childList);
        for (SysOrganizationVO child : childList) {
            if (hasChild(vos, child)) {
                recursionFn(vos, child);
            }
        }
    }
    /**
     * 获取子节点列表
     */
    private List<SysOrganizationVO> getChildList(List<SysOrganizationVO> vos, SysOrganizationVO vo) {
        List<SysOrganizationVO> childList = new ArrayList<>();
        for (SysOrganizationVO n : vos) {
            if (n.getPaId() != null && Objects.equals(n.getPaId(), vo.getId())) {
                childList.add(n);
            }
        }
        return childList;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysOrganizationVO> vos, SysOrganizationVO vo) {
        return getChildList(vos, vo).size() > 0;
    }

    @Override
    public List<Object> loadDataSource() {
        List<SysOrganizationEntity> entityList = listAllOrgWithCache();
        return entityList.stream().map(e->Convert.convert(SysOrganizationEntity.class,e)).collect(Collectors.toList());
    }
}
